package com.example.hello.views.users;

import com.example.hello.*;
import com.example.hello.POJO.OrganizationPOJO;
import com.example.hello.POJO.UserPOJO;
import com.example.hello.views.Wireframe1;
import com.example.hello.views.organizations.Organizations;
import com.vaadin.navigator.View;
import com.vaadin.navigator.ViewChangeListener;
import com.vaadin.ui.Alignment;
import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.VerticalLayout;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.map.ObjectWriter;
import org.codehaus.jackson.type.TypeReference;

import java.io.IOException;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;

public class Users extends VerticalLayout implements View {

    public static final String NAME = "users";
    
    private static UserPOJO currentUser;
    private static Set<UserPOJO> users = new HashSet<>();

    private VerticalLayout layout = new VerticalLayout();

    private HorizontalLayout add = new HorizontalLayout();
    private BootstrapButton view = new BootstrapButton("View", BootstrapButton.Size.SMALL);
    private BootstrapButton delete = new BootstrapButton("Delete", BootstrapButton.Size.SMALL);

    private StringWrap selectedUser = new StringWrap();

    @Override
    public void enter(ViewChangeListener.ViewChangeEvent event) {
        currentUser = ((HelloUI) HelloUI.getCurrent()).getUser();
        if (currentUser == null) currentUser = new UserPOJO();
//        users = GETUsers("");
//        if (users == null) users = new HashSet<>();

        add.setVisible(currentUser.isSiteAdmin());
        delete.setVisible(currentUser.isSiteAdmin());
        if (currentUser.isSiteAdmin()) {
            view.setWidth("110px");
        } else {
            view.setWidth("220px");
        }

        /** Redirect to User View if needed **/
        String[] parameters = event.getParameters().split("/");
        if (!parameters[0].equals("")) {
            UserPOJO user = User.GETUser(parameters[0]);
            if (user != null) {
                User userView = new User(Users.NAME + "/" + user.getEncodedName(), false, user, null);
                getUI().getNavigator().addView(userView.NAME, userView);
                String tab = "";
                if (parameters.length > 1 && parameters[1] != null && parameters[1].contains("?tab="))
                    tab = "/" + parameters[1];
                getUI().getNavigator().navigateTo(userView.NAME + tab);
            } else {
                getUI().getNavigator().navigateTo(NAME);
            }
        }
    }

    public Users() {
        setWidth("100%");

        currentUser = ((HelloUI) HelloUI.getCurrent()).getUser();
        if (currentUser == null) currentUser = new UserPOJO();
        users = GETUsers("");
        if (users == null) users = new HashSet<>();

        initUsers();

        addComponent(layout);
        setComponentAlignment(layout, Alignment.TOP_CENTER);
    }

    private void initUsers() {
        final ListBox userList = new ListBox();
        delete.setWidth("110px");

        userList.setVisibleItems(16);
        for (UserPOJO user : users) userList.addItem(user.getUserName());
        Collections.sort(userList.getItems());
        if (userList.getItems().size() != 0) {
            selectedUser.setString(userList.getItems().get(0));
        } else {
            view.setEnabled(false);
            delete.setEnabled(false);
            
        }
        userList.addListener(new Listener() {
            @Override
            public void componentEvent(Event event) {
                if (event instanceof ListBoxChangeEvent)
                    selectedUser.setString(((ListBoxChangeEvent) event).getSelected());
            }
        });
        view.addListener(new Listener() {
            @Override
            public void componentEvent(Event event) {
                getUI().getNavigator().navigateTo(NAME + "/" + selectedUser.toString());
            }
        });
        delete.addListener(new Listener() {
            @Override
            public void componentEvent(Event event) {
                removeUser(User.GETUser(selectedUser.getEncoded()));
                getUI().getNavigator().navigateTo(NAME);
            }
        });

        HorizontalLayout buttons = new HorizontalLayout(view, delete);

        // add userList for display
        layout.addComponents(userList, buttons);
        layout.setComponentAlignment(userList, Alignment.TOP_CENTER);
        layout.setComponentAlignment(buttons, Alignment.TOP_CENTER);
    }

    public static Set<UserPOJO> GETUsers(String query) {
        Set<UserPOJO> users = new HashSet<>();
        try {
            String json = HttpRequest.GET(Users.NAME + query);
            ObjectMapper mapper = new ObjectMapper();
            users = mapper.readValue(json, new TypeReference<Set<UserPOJO>>() {
            });
        } catch (IOException e) {
            e.printStackTrace();
        }
        return users;
    }

    public static Set<UserPOJO> getUsers() {
        return users;
    }

    public static void setUsers(Set<UserPOJO> users) {
        Users.users = users;
    }

    public static boolean addUser(UserPOJO user) {
        // post a user to get an _id
        if (!HttpRequest.executePost(NAME, user.toJSON())) return false;

        // get the user with _id attached
        user = User.GETUser(user.getEncodedName());
        if (!users.contains(user)) users.add(user);

        // create the View with the user
        User userView = new User(Users.NAME + "/" + user.getEncodedName(), false, user, null);
        HelloUI.getCurrent().getNavigator().addView(userView.NAME, userView);

        return true;
    }

    public static boolean removeUser(UserPOJO user) {
        // get all linked resources and update or relocate
        Set<OrganizationPOJO> adminOrgs = Organizations.GETOrganizations("?=admin" + user.getEncodedName());
        Set<OrganizationPOJO> userOrgs = Organizations.GETOrganizations("?=user" + user.getEncodedName());
        for (OrganizationPOJO org : adminOrgs) {
            if (org.removeUser(user.getEncodedName())) org.update();
        }
        for (OrganizationPOJO org : userOrgs) {
            if (org.removeUser(user.getEncodedName())) org.update();
        }

        // delete the user
        HttpRequest.executeDelete(NAME + "/" + user.getEncodedName());
        HelloUI.getCurrent().getNavigator().removeView(NAME + "/" + user.getEncodedName());

        return users.remove(user);
    }

    public static boolean hasUser(UserPOJO user) {
        return users.contains(user);
    }

}